﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;

namespace HighestCPUProcess {
    class Program {
        static void Main2() {
            var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");

            var processes = Process.GetProcesses();
            var processInfos = new ProcessInfo[processes.Length];
            const bool parallel = true;

            if (parallel) {
                Parallel.ForEach(processes, (process, _, index) => {
                    processInfos[index] = new ProcessInfo {
                        ProcessName = process.ProcessName,
                        // CpuUsage = GetCpuUsageForProcess(cpuCounter, process)
                        CpuUsage = GetCpuUsageForProcess2(process)
                    };
                });
            } else {
                for (int i = 0; i < processes.Length; i++) {
                    var process = processes[i];
                    processInfos[i] = new ProcessInfo {
                        ProcessName = process.ProcessName,
                        CpuUsage = GetCpuUsageForProcess2(process)
                    };
                }
            }

            var topFive = processInfos
                .OrderByDescending(x => x.CpuUsage)
                .Take(5);

            foreach (var process in topFive) {
                Console.WriteLine($"Process: {process.ProcessName} CPU: {process.CpuUsage}");
            }
            Console.ReadKey();
        }

        static void Main(string[] args) {
            var instanceNames = new PerformanceCounterCategory("Process").GetInstanceNames();
            SortedSet<string> dd = new SortedSet<string>();
            dd.UnionWith(instanceNames);
            var ee = dd.Count(name => name.StartsWith("firefox"));

            // 以下为正确答案
            var processName = "firefox"; // Replace with the name of the process you want to monitor
            var processId = 64400; // Replace with the process ID you want to monitor
            var instanceName = new PerformanceCounterCategory("Process").GetInstanceNames().FirstOrDefault(name => name.StartsWith(processName) && new PerformanceCounter("Process", "ID Process", name, true).RawValue == processId);
            var cpuUsage = new PerformanceCounter("Process", "% Processor Time", instanceName, true);
            Thread.Sleep(1000);
            var firstCall = cpuUsage.NextValue();
            for (int i = 0; i < 5; i++) {
                Thread.Sleep(1000);
                Console.WriteLine(cpuUsage.NextValue() + "%");
            }
            Console.Read();
        }


        static float GetCpuUsageForProcess2(Process process) {
            try {
                var pc = new PerformanceCounter("Process", "% Processor Time", process.ProcessName);
                pc.NextValue();
                float v1 = pc.NextValue();
                // float v2 = pc.NextValue();
                float v2 = v1;
                return (v1 + v2) / 2;
            }
            catch (Exception ex) {
                Console.WriteLine("Exception occured when create pc, " + process.ProcessName + ": " + ex.Message);
                return 0;
            }
        }

        static float GetCpuUsageForProcess(PerformanceCounter cpuCounter, Process process) {
            try {
                var startTime = DateTime.UtcNow;
                var startCpuUsage = process.TotalProcessorTime;
                var startTotalCpuUsage = cpuCounter.NextValue();

                Thread.Sleep(100);

                var endTime = DateTime.UtcNow;
                var endCpuUsage = process.TotalProcessorTime;
                var endTotalCpuUsage = cpuCounter.NextValue();

                var cpuUsedMs = (endCpuUsage - startCpuUsage).TotalMilliseconds;
                var totalMsPassed = (endTime - startTime).TotalMilliseconds;
                var cpuUsageTotal = (endTotalCpuUsage - startTotalCpuUsage) / totalMsPassed;

                var cpuUsage = cpuUsageTotal * cpuUsedMs;

                return (float)cpuUsage;
            }
            catch {
                return 0;
            }
        }

    }

    struct ProcessInfo {
        public string ProcessName;
        public float CpuUsage;
    }
}